import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Rectangle;
import java.sql.Time;
import java.util.ArrayList;

import javax.swing.ImageIcon;

public class Character implements GameObject {

	private int upKey, downKey, leftKey, rightKey, jumpKey, actionKey; // Keys
	private int xSpeed, ySpeed, x, y, bonusX, bonusY, speed, width, height, gravity, jumps, jumpDuration, durationLeft, jumpSpeed; // Movement
	private int state;
	private boolean jumping, direction, living, playerID;
	private long jumpStart;
	private Image sprite;
	private Time timer;
	private ArrayList collisionListCollection;
	private final boolean LEFT = false;
	private final boolean RIGHT = true;
	private final int STATIC_OBJECT = 1;
	private GameObject b;
	private boolean[] keyPressed;
	private ArrayList<Projectile> projectiles;

	public Character(int x, int y, String spritePath, ArrayList collisionListCollection, boolean playerID) {
		this.x = x;
		this.y = y;
		speed = 5;
		xSpeed = 0;
		ySpeed = 0;
		bonusX = 0;
		bonusY = 0;
		gravity = 6;
		jumps = 0;
		jumpSpeed = 16;
		this.playerID = playerID;
		// jumpStart = 0;
		jumpDuration = 7;
		durationLeft = 0;
		jumping = false;
		this.collisionListCollection = collisionListCollection;
		direction = LEFT;
		living = true;
		state = 0;

		ImageIcon ii = new ImageIcon(this.getClass().getResource(spritePath));
		sprite = ii.getImage();

		width = sprite.getWidth(null);
		height = sprite.getHeight(null);

		keyPressed = new boolean[500];

		projectiles = new ArrayList<Projectile>();
	}

	private void addProjectile(int x, int y, int type, int xSpeed, int ySpeed) {
		if (type == 0)
			projectiles.add(new Projectile(x, y, type, xSpeed, ySpeed, "images/blueprojectile.png", collisionListCollection));
		else if (type == 1)
			projectiles.add(new Projectile(x, y, type, xSpeed, ySpeed, "images/redprojectile.png", collisionListCollection));
	}

	public void shoot() {
		if (direction == LEFT) {
			addProjectile(x - 8, y + 6, state, -10, 0);
		} else if (direction == RIGHT) {
			addProjectile(x + 16, y + 6, state, 10, 0);
		}
	}

	private boolean keyPressed(int key) {
		return keyPressed[key];
	}

	public ArrayList<Projectile> getProjectiles() {
		return projectiles;
	}

	public void pressKey(int key) {
		keyPressed[key] = true;
	}

	public void releaseKey(int key) {
		keyPressed[key] = false;
	}

	public void jump() {
		if (jumping == false && (collision(30) == 1) || collision(30) == 20) {
			jumping = true;
			ySpeed = -jumpSpeed;
			durationLeft = jumpDuration;
		} else if (jumps > 0 && jumping == false) {
			jumping = true;
			ySpeed = -jumpSpeed;
			durationLeft = (int) (jumpDuration * 0.85);
			jumps -= 1;
		}
	}

	public void kill() {
		living = false;
	}

	public void stopJump() {
		// ySpeed = 0;
		jumping = false;
	}

	public void setXSpeed(int speed) {
		xSpeed = speed;
	}

	public void setYSpeed(int speed) {
		ySpeed = speed;
	}

	public void move() {
		// x += xSpeed;
		/*
		 * while (collision() == STATIC_OBJECT) { if (collision() ==
		 * STATIC_OBJECT) { if ((xSpeed) < 0) { x += 1; } else if ((xSpeed) > 0)
		 * { x -= 1; } } }
		 */
		x += collision(10);
		if (xSpeed < 0) {
			direction = LEFT;
		} else if (xSpeed > 0) {
			direction = RIGHT;
		}
		y += collision(20);/*
							 * y += ySpeed + gravity; while (collision() ==
							 * STATIC_OBJECT) { if (collision() ==
							 * STATIC_OBJECT) { if ((ySpeed + gravity) < 0) { y
							 * += 1; } else if ((ySpeed + gravity) > 0) { jumps
							 * = 1; y -= 1; } } }
							 */
		if (durationLeft < 0) {
			ySpeed = 0;
		} else {
			durationLeft--;
		}
		/*
		 * else if(jumpStart+jumpDuration - System.currentTimeMillis() < 225){
		 * ySpeed = -6; } else if(jumpStart+jumpDuration -
		 * System.currentTimeMillis() < 150){ ySpeed = -4; } else
		 * if(jumpStart+jumpDuration - System.currentTimeMillis() < 75){ ySpeed
		 * = -2; }
		 */
	}

	public void specialAction() {
		if (playerID) {
			shoot();
		} else {

		}
	}

	public void setSpeed(int speed) {
		this.speed = speed;
	}

	public int getSpeed() {
		return speed;
	}

	public boolean isLiving() {
		return living;
	}

	public void changeState() {
		if (!keyPressed(downKey)) {
			pressKey(downKey);
			state++;
			if (state > 1)
				state = 0;
		}
		System.out.println("\n" + state + " " + downKey);
	}

	public void draw(Graphics2D g2d, Game observer) {
		g2d.drawImage(sprite, x, y, observer);
	}

	public int collision(int collisionType) {
		if (collisionType >= 10 && collisionType < 20) {
			Rectangle rM = new Rectangle(x + xSpeed + bonusX, y, width, height);
			GameObject savedObject = null;
			for (int i = 0; i < collisionListCollection.size(); i++) {
				ArrayList objects = (ArrayList) collisionListCollection.get(i);
				for (int j = 0; j < objects.size(); j++) {
					b = (GameObject) objects.get(j);
					if (!(b == this)) {
						Rectangle rB = new Rectangle(b.getX(), b.getY(), b.getWidth(), b.getHeight());

						if (rM.intersects(rB)) {
							if (b.getType() == 100) {
								System.exit(1337);
							}
							if (b.getType() == 1 || b.getType() == 2 || b.getType() == 20) {
								if (b.getType() == 20) {
									b.specialFunction(1);
								}
								if (b.getType() == 1 || b.getType() == 20) {
									if (xSpeed+bonusX > 0) {
										return (b.getX() - x - width);
									} else if (xSpeed+bonusX < 0) {
										return (b.getX() + b.getWidth() - x);
									}
								} else if (b.getType() == 2 && !(collisionType == 11)) {
									savedObject = b;
								}
							}
						}
					}
				}
			}
			if (savedObject != null) {
				if (x < savedObject.getX())
					rM = new Rectangle(savedObject.getX() - width, y, width, height);
				else
					rM = new Rectangle(savedObject.getX() + width, y, width, height);
				for (int i = 0; i < collisionListCollection.size(); i++) {
					ArrayList objects = (ArrayList) collisionListCollection.get(i);
					for (int j = 0; j < objects.size(); j++) {
						b = (GameObject) objects.get(j);
						if (!(b == this)) {
							Rectangle rB = new Rectangle(b.getX(), b.getY(), b.getWidth(), b.getHeight());

							if (rM.intersects(rB)) {
								if (b.getType() == 100) {
									System.exit(1337);
								}
								if (b.getType() == 1 || b.getType() == 2 || b.getType() == 20) {
									if (b.getType() == 20) {
										b.specialFunction(1);
									}
									living = false;
									System.out.println("DEAD!!!!!");
									return 0;
								}
							}
						}
					}
				}
				if (x < savedObject.getX()) {
					return savedObject.getX() - x - width;
				} else {
					return savedObject.getX() + savedObject.getWidth() - x;
				}
			} else {
				return xSpeed + bonusX;
			}
		} else if (collisionType >= 20 && collisionType < 30) {
			Rectangle rM = new Rectangle(x, y + ySpeed + gravity + bonusY, width, height);
			GameObject savedObject = null;
			for (int i = 0; i < collisionListCollection.size(); i++) {
				ArrayList objects = (ArrayList) collisionListCollection.get(i);
				for (int j = 0; j < objects.size(); j++) {
					b = (GameObject) objects.get(j);
					if (!(b == this)) {
						Rectangle rB = new Rectangle(b.getX(), b.getY(), b.getWidth(), b.getHeight());

						if (rM.intersects(rB)) {
							if (b.getType() == 1 || b.getType() == 2 || b.getType() == 20) {
								if (b.getType() == 1 || b.getType() == 20) {
									bonusX = 0;
									if (b.getType() == 20) {
										b.specialFunction(1);
									}
									if (ySpeed + gravity > 0) {
										jumps = 1;
										return (b.getY() - y - height);
									} else if (ySpeed + gravity < 0) {
										return (b.getY() + b.getHeight() - y);
									}
								} else if (b.getType() == 2 && !(collisionType == 11)) {
									System.out.println(b.getXSpeed());
									bonusX = b.getXSpeed();
									savedObject = b;
								}
							}
						}
					}
				}
			}
			if (savedObject != null) {
				if (y < savedObject.getY())
					rM = new Rectangle(savedObject.getX(), savedObject.getY() - height, width, height);
				else
					rM = new Rectangle(savedObject.getX(), savedObject.getY() + height, width, height);
				for (int i = 0; i < collisionListCollection.size(); i++) {
					ArrayList objects = (ArrayList) collisionListCollection.get(i);
					for (int j = 0; j < objects.size(); j++) {
						b = (GameObject) objects.get(j);
						if (!(b == this)) {
							Rectangle rB = new Rectangle(b.getX(), b.getY(), b.getWidth(), b.getHeight());

							if (rM.intersects(rB)) {
								if (b.getType() == 1 || b.getType() == 2 || b.getType() == 20) {
									living = false;
									return 0;
								}
							}
						}
					}
				}
				if (y < savedObject.getY()) {
					jumps = 1;
					return savedObject.getY() - y - height;
				} else {
					return savedObject.getY() + savedObject.getHeight() - y;
				}
			} else {
				bonusX = 0;
				return ySpeed + gravity;
			}
		} else if (collisionType >= 30 && collisionType < 40) {
			Rectangle rM = new Rectangle(x, y + 17, width, 1);
			for (int i = 0; i < collisionListCollection.size(); i++) {
				ArrayList objects = (ArrayList) collisionListCollection.get(i);
				for (int j = 0; j < objects.size(); j++) {
					b = (GameObject) objects.get(j);
					if (!(b == this)) {
						Rectangle rB = new Rectangle(b.getX(), b.getY(), b.getWidth(), b.getHeight());

						if (rM.intersects(rB) && (b.getType() == 1 || b.getType() == 2 || b.getType() == 20)) {
							return 1;
						}
					}
				}
			}
			return 0;
		} else {
			return 0;
		}
	}

	/*
	 * 
	 * GET KEYS:
	 */

	public int getUpKey() {
		return upKey;
	}

	public int getDownKey() {
		return downKey;
	}

	public int getLeftKey() {
		return leftKey;
	}

	public int getRightKey() {
		return rightKey;
	}

	public int getJumpKey() {
		return jumpKey;
	}

	public int getActionKey() {
		return actionKey;
	}

	/*
	 * END OF GET KEYS
	 * 
	 * SET KEYS:
	 */
	public void setUpKey(int key) {
		upKey = key;
	}

	public void setDownKey(int key) {
		downKey = key;
	}

	public void setLeftKey(int key) {
		leftKey = key;
	}

	public void setRightKey(int key) {
		rightKey = key;
	}

	public void setJumpKey(int key) {
		jumpKey = key;
	}

	public void setActionKey(int key) {
		actionKey = key;
	}

	/*
	 * END OF SET KEYS
	 */

	@Override
	public int getX() {
		return x;
	}

	@Override
	public int getY() {
		return y;
	}

	@Override
	public int getWidth() {
		return width;
	}

	@Override
	public int getHeight() {
		return height;
	}

	@Override
	public int getType() {
		return 0;
	}

	@Override
	public int getYSpeed() {
		return ySpeed;
	}

	@Override
	public int getXSpeed() {
		return xSpeed;
	}

	@Override
	public void specialFunction(int type) {
	}

	public int projectileCollision(int type) {
		return -1;
	}
}
